package com.cloud.charts4a.chart.render;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import com.cloud.charts4a.chart.TimeChart.XAxisAttribs;
import com.cloud.charts4a.chart.attrib.YAxisAttribs;
import com.cloud.charts4a.chart.attrib.YRangeHighLightAttribs;
import com.cloud.charts4a.data.TimeChartData;
import com.cloud.charts4a.data.ChartDataSeries;
import android.graphics.Canvas;
import android.graphics.Paint;

/**
 * Time Chart Render<p/>
 * 
 * @version
 * <ol>
 * 	<li>2010/07/09 CloudTu：First Release</li>
 * </ol>
 * 
 * @author Cloud Tu
 */
public class TimeChartRender extends AbstractChartRender<XAxisAttribs, TimeChartData> {	 			
	/**
	 * 一分鐘代表的milliseconds
	 */
	private static final int ONE_MINUTE_AS_MILLISECS = 60 * 1000;
	
	/**
	 * X軸標籤在顯示時所使用的日期格式物件
	 */
	private SimpleDateFormat xAxisLabelDateFormat;
	
	/**
	 * 圖上資料被點擊時，顯示出來提示文字裡，日期部份所使用的日期格式物件
	 */
	private SimpleDateFormat tipDateFormat;	
	
	/**
	 * Time Chart Render
	 * 
	 * @param canvas					Canvas
	 * @param canvasWidth				Canvas width
	 * @param canvasHeight				Canvas Height
	 * @param oneDipToPixel				一單位dip(Density-independent pixel)轉換成Pixel後的值
	 * @param xAxisAttribs				XAxisAttribs
	 * @param yAxisAttribs				YAxisAttribs
	 * @param yRangeHighLightAttribs	YRangeHighLightAttribs
	 * @param chartDataSeriesList		TimeChartDataSeries List
	 * @param tipDateFormat				折線點被點擊時，顯示出來提示文字裡，日期部份的日期格式物件
	 * @param isOnlyShowDot				是否只顯示折線點
	 * @param isShowLegend				是否要顯示圖例
	 * @param isShowXUnitDesc			是否要顯示X軸的單位說明
	 * @param isShowYUnitDesc			是否要顯示Y軸的單位說明
	 */
	public TimeChartRender(Canvas canvas, float canvasWidth,float canvasHeight,float oneDipToPixel,
						   XAxisAttribs xAxisAttribs,YAxisAttribs yAxisAttribs,
						   YRangeHighLightAttribs yRangeHighLightAttribs,List<ChartDataSeries<TimeChartData>> chartDataSeriesList,
						   SimpleDateFormat tipDateFormat,boolean isOnlyShowDot,boolean isShowLegend,
						   boolean isShowXUnitDesc,boolean isShowYUnitDesc){
		this.canvas = canvas;
		this.canvasWidth = canvasWidth;
		this.canvasHeight = canvasHeight;
		this.xAxisAttribs = xAxisAttribs;
		this.yAxisAttribs = yAxisAttribs;		
		this.yRangeHighLightAttribs = yRangeHighLightAttribs;
		this.chartDataSeriesList = chartDataSeriesList;		
		this.isOnlyShowDot = isOnlyShowDot;
		this.isShowLegend = isShowLegend;
		this.isShowXUnitDesc = isShowXUnitDesc;
		this.isShowYUnitDesc = isShowYUnitDesc;		
		
		xAxisLabelDateFormat = new SimpleDateFormat(xAxisAttribs.getDateFormat());
		this.tipDateFormat = tipDateFormat;		
		
		chartRenderBo = new ChartRenderBo(oneDipToPixel);
		
		xyAxisPaint = chartRenderBo.createXYAxisPaint();
		xyAxisBackgroundGridPaint = chartRenderBo.createXYAxisBackgroundGridPaint();		
		xyAxisLabelPaint = chartRenderBo.createXYAxisLabelPaint();
		xyAxisUnitDescPaint = chartRenderBo.createXYAxisUnitDescPaint();	
		
		initXAxisLabelsValue();
		initYAxisLabelsValue();
		initLegendsValue();						
		
		xAxisIntervalForTwoXAxisLabelUnit = chartRenderBo.calXAxisIntervalForTwoXAxisLabelUnit(canvasWidth, isShowYUnitDesc, "" + yAxisLabels[yAxisLabels.length - 1],
																		 xAxisLabels.length,xAxisLabels[xAxisLabels.length -1], xyAxisLabelPaint, xyAxisUnitDescPaint);
		yAxisIntervalForTwoYAxisLabelUnit = chartRenderBo.calYAxisIntervalForTwoYAxisLabelUnit(canvasWidth, canvasHeight, yAxisLabels.length,
																		 isShowXUnitDesc, isShowLegend, legends, xyAxisLabelPaint, xyAxisUnitDescPaint);		
		xAxisUnitDescHeight = chartRenderBo.calXAxisUnitDescHeight(isShowXUnitDesc,xyAxisUnitDescPaint);
		xAxisUnitDescHeightWithTopAndBottomPad = chartRenderBo.calXAxisUnitDescHeightWithTopAndBottomPad(isShowXUnitDesc,xyAxisUnitDescPaint);
		yAxisUnitDescHeightWithTopAndBottomPad = chartRenderBo.calYAxisUnitDescHeightWithTopAndBottomPad(isShowYUnitDesc,xyAxisUnitDescPaint);		
		xyAxisLabelHeight = chartRenderBo.calXAxisLabelOrYAxisLabelHeight(xyAxisLabelPaint);			
		xAxisLabelHeightWithTopAndBottomPad = chartRenderBo.calXAxisLabelHeightWithTopAndBottomPad(xyAxisLabelPaint);		
		yAxisLabelWidthWithLeftAndRightPad = chartRenderBo.calYAxisLabelWidthWithLeftAndRightPad("" + yAxisLabels[yAxisLabels.length-1],xyAxisLabelPaint);
		oneLegendUnitHeightWithTopAndBottomPad = chartRenderBo.calOneLegendHeightWithTopAndBottomPad();		
		totalLegendsHeightWithTopAndBottomPad = chartRenderBo.calTotalLegendsHeightWithTopAndBottomPad(isShowLegend,legends,canvasWidth);
	}
	
	@Override
	protected void initXAxisLabelsValue(){		
		Date minXDate = xAxisAttribs.getMinXValue();
		Date maxXDate = xAxisAttribs.getMaxXValue();
		int xDateInterval = xAxisAttribs.getXValueInterval();	//相臨二個xAxisLabel間所代表的實際日期間隔多長(單位為分鐘)
		long minXDateAsMilliseconds = minXDate.getTime();
		long maxXDateAsMilliseconds = maxXDate.getTime();	
		
		//maxXDate-minXDate的日期區間必需能被xDateInterval整除。無法整除時，maxXDate自動增量至可被整除的日期
		int rate = (int)Math.ceil((((double)maxXDateAsMilliseconds - minXDateAsMilliseconds) / ONE_MINUTE_AS_MILLISECS) / xDateInterval);
		maxXDate.setTime(minXDateAsMilliseconds + ONE_MINUTE_AS_MILLISECS * xDateInterval * rate);
	
		maxXDateAsMilliseconds = maxXDate.getTime();						
		long startDateAsMilliseconds = minXDateAsMilliseconds;
		xAxisLabels = new String[rate + 1];
		for(int i=0;i< xAxisLabels.length;i++){			
			xAxisLabels[i] = xAxisLabelDateFormat.format(new Date(startDateAsMilliseconds));
			startDateAsMilliseconds = startDateAsMilliseconds + ONE_MINUTE_AS_MILLISECS * xDateInterval;
		}
	}
	
	@Override
	protected void drawContents(){		
		float yIntervalForOneUnitValueInChart = yAxisIntervalForTwoYAxisLabelUnit / (yAxisLabels[1] - yAxisLabels[0]);	//Chart圖表Y軸上一個單位值所對應的Pixel長度		
		float xPositionForXAxisReferencePointInChart = yAxisUnitDescHeightWithTopAndBottomPad + yAxisLabelWidthWithLeftAndRightPad +
												 	   xAxisIntervalForTwoXAxisLabelUnit / 2;	//Chart圖表在X軸參考點(原點+半格X軸間格)時，對應在Canvas畫面上的X座標值				
		float yPositionForYAxisOriginInChart = xAxisLabelHeightWithTopAndBottomPad + 
											   yAxisIntervalForTwoYAxisLabelUnit * (yAxisLabels.length - 1);	//Chart圖表在Y軸原點時，對應在Canvas畫面上的Y座標值				
		
		
		if(yRangeHighLightAttribs != null){
			//畫HightLight的Y軸區塊					
			canvas.drawRect(xPositionForXAxisReferencePointInChart - xAxisIntervalForTwoXAxisLabelUnit / 2,
					yPositionForYAxisOriginInChart - (yRangeHighLightAttribs.getMaxYValue() - yAxisLabels[0]) * yIntervalForOneUnitValueInChart,
					xPositionForXAxisReferencePointInChart + (xAxisLabels.length - 1) * xAxisIntervalForTwoXAxisLabelUnit,
					yPositionForYAxisOriginInChart - (yRangeHighLightAttribs.getMinYValue() - yAxisLabels[0]) * yIntervalForOneUnitValueInChart,
					chartRenderBo.createYRangeHighLightRectPaint(yRangeHighLightAttribs.getColor()));				
		}					
			
		
		if(chartDataSeriesList.size() > 0){
			long minXDateAsMilliseconds = xAxisAttribs.getMinXValue().getTime();
			long maxXDateAsMilliseconds = xAxisAttribs.getMaxXValue().getTime();		
			float xPixelIntervalForOneMillisecondsUnitInChart = xAxisIntervalForTwoXAxisLabelUnit / (xAxisAttribs.getXValueInterval()* 60 * 1000);	//Chart圖表X軸上一毫秒時間所對應的Pixel長度			
			Paint tipTextPaint = chartRenderBo.createTipTextPaint();
			for (ChartDataSeries<TimeChartData> chartDataSeries : chartDataSeriesList) {
				//開始畫折線前要先將來源資料進行排序
				chartDataSeries.sort();
				
				//設定存折線點在Canvas畫面上的座標值、提示文字、提示文字背景框...etc
				for(int i=0;i<chartDataSeries.size();i++){
					TimeChartData chartData = chartDataSeries.getChartData(i);
					
					long dateAsMillisecondsInTimeChartData = chartData.getXDate().getTime();
					if(dateAsMillisecondsInTimeChartData >= minXDateAsMilliseconds && dateAsMillisecondsInTimeChartData <= maxXDateAsMilliseconds){
						chartData.setXPosition(xPositionForXAxisReferencePointInChart + 
											   (dateAsMillisecondsInTimeChartData - minXDateAsMilliseconds) * xPixelIntervalForOneMillisecondsUnitInChart);					
						chartData.setYPosition(yPositionForYAxisOriginInChart - (chartData.getYValue() - yAxisLabels[0]) * yIntervalForOneUnitValueInChart);																							
						chartData.setTipText(chartDataSeries.getName() + " , " + tipDateFormat.format(chartData.getXDate()) + " , " + tipDecimalFormat.format(chartData.getYValue()));
						chartData.setTipRect(chartRenderBo.calTipRect(canvasWidth, chartData, tipTextPaint));
					}	
					else{
						chartData.setXPosition(null);
						chartData.setShowTip(false);
					}
				}
				
				if(isOnlyShowDot == false){
					//畫量測值的折線
					Paint seriesLinePaint = chartRenderBo.createDataSeriesLinePaint(chartDataSeries.getColor());
					for(int i=0;i<chartDataSeries.size();i++){
						if(i != chartDataSeries.size()-1){
							TimeChartData startChartData = chartDataSeries.getChartData(i);
							TimeChartData endChartData = chartDataSeries.getChartData(i+1);							
							if(startChartData.getXPosition() != null && endChartData.getXPosition() != null){
								canvas.drawLine(startChartData.getXPosition(), startChartData.getYPosition(), endChartData.getXPosition(), endChartData.getYPosition(), seriesLinePaint);
							}							
						}			
					}					
				}				
				
				//畫量測值的折線點
				Paint seriesDotPaint = chartRenderBo.createDataSeriesDotPaint(chartDataSeries.getColor());
				for(int i=0;i<chartDataSeries.size();i++){
					TimeChartData chartData = chartDataSeries.getChartData(i);					
					if(chartData.getXPosition()!= null){
						canvas.drawRect(chartData.getXPosition() - chartRenderBo.dataSeriesDotRadias, chartData.getYPosition() - chartRenderBo.dataSeriesDotRadias,
										chartData.getXPosition() + chartRenderBo.dataSeriesDotRadias, chartData.getYPosition() + chartRenderBo.dataSeriesDotRadias, seriesDotPaint);
					}							
				}				
			}									
		}	
	}
}
